#!/usr/bin/env python

# pylazy: report on how do you spend your time with
# Copyright (C) 2008 Jordi Carrillo Bosch (jordilin)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Don't send the final report to your boss, just in case ;-)

from __future__ import division
import os,time,sys,webbrowser
from subprocess import *
import logging,logging.handlers
from optparse import OptionParser
        
try:
    import matplotlib.pyplot as pypl
except:
    print "make sure you've got matplotlib and Tkinter"       
    sys.exit()


logfile = os.getenv('PWD')+"/pylazy.log"
lazylogger = logging.getLogger('pylazy.py')
lazylogger.setLevel(logging.INFO)
lazyhandler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
lazyhandler.setFormatter(formatter)
lazylogger.addHandler(lazyhandler)


def getApps():
    availableApps = []
    appDirs = ['/usr/bin','/bin']
    for appdir in appDirs:
        availableApps += os.listdir(appdir)
    return availableApps


class Lazy:
    '''How do you spend your time?'''
    def __init__(self):
        self.count = 0
        self.app = {}

    def sumPercentage(self,appName):
        if appName in self.app:
            self.app[appName] += 1
        else:
            self.app[appName] = 1

    def getPercentages(self):
        return self.app


class Command:
    '''Commands to take into account
    1) xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)" takes the window id
    output:
    _NET_ACTIVE_WINDOW(WINDOW): window id # 0x460000a

    2) xwininfo -id 0x460000a give us the app title in window bar
    output:

    xwininfo: Window id: 0x3401821 "Catradio.cat - Mozilla Firefox"

    Absolute upper-left X:  2
    Absolute upper-left Y:  66
    Relative upper-left X:  2
    Relative upper-left Y:  66
    Width: 650
    Height: 504
    Depth: 24
    Visual Class: TrueColor
    Border width: 0
    Class: InputOutput
    Colormap: 0x20 (installed)
    Bit Gravity State: NorthWestGravity
    Window Gravity State: NorthWestGravity
    Backing Store State: NotUseful
    Save Under State: no
    Map State: IsViewable
    Override Redirect State: no
    Corners:  +2+66  -628+66  -628-230  +2-230
    -geometry 650x504+2+66 '''
    
    def __init__(self):
        self.getId = "xprop -root | grep '_NET_ACTIVE_WINDOW(WINDOW)'"
        self.getTitle = "xwininfo -id "
        self.apps = getApps()

    def runGetId(self):
        proc = Popen(self.getId, shell=True,stdout=PIPE, stderr=PIPE)
        res,err = proc.communicate()
        if err:
            return None
        id = (res.split('#'))[1].strip()
        lazylogger.debug(id)
        return id

    def runGetTitle(self,id):
        title = None
        cmd = self.getTitle+id
        proc = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
        res,err = proc.communicate()
        if err:
            lazylogger.error(err)
            return None
        lazylogger.debug(res)
        possibleTitle = res.split("\n")[1]
        lazylogger.debug("possible title: "+possibleTitle)
        if "-" in possibleTitle:
            title = possibleTitle.split('-')[-1].strip()[:-1]
        elif "@" in possibleTitle:
            title = "shell"
        elif ("jpg" or "jpeg") in possibleTitle:
            title = "pics"
        elif "pdf" in possibleTitle:
            title = "pdf"
        else:
            title = possibleTitle.split('"')[1]
            if title not in self.apps:
                title = 'Pidgin'

        lazylogger.info(title)
        return title

class Report:
    '''base class for Reports 
	being Pie Charts or Stdout Reports'''

    def __init__(self,data):
        self.data = data
        self.keys = data.keys()
        self.values = data.values()
        self.totals = 0
        self.percentage = 0
        self.labels = []
        self.fracs = []

    def calculate(self):
        for value in self.values:
            self.totals += value
        lazylogger.debug( self.totals)
        for key in self.keys:
            lazylogger.debug("before: "+str(self.data[key]))
            self.data[key] = (self.data[key] / self.totals) * 100
            lazylogger.debug("after: "+str(self.data[key]))

    def show(self):
        pass


class PieMatplotLib(Report):
    '''Creates a pie chart using 
    Matplotlib'''

    def __init__(self,data):
        Report.__init__(self,data)

    def show(self):
        pypl.figure(1, figsize=(8,8))
        ax = pypl.axes([0.1, 0.1, 0.8, 0.8])
        lazylogger.debug(self.data.keys())
        lazylogger.debug(self.data.values())
        pypl.pie(self.data.values(),labels=self.data.keys(), autopct='%1.1f%%', shadow=True)
        pypl.title('How Lazy are you?', bbox={'facecolor':'0.8', 'pad':5})
        pypl.show()


class PieGChart(Report):
    '''Creates a pie chart to 
    be showed in the web browser'''
    
    def __init__(self,data):
        Report.__init__(self,data)
    
    def show(self):
        try:
            from pygooglechart import PieChart2D
        except:
            print """you need python google chart wrapper python-pygooglechart
                  in Ubuntu or Debian systems. It can be downloaded 
                  in http://pygooglechart.slowchop.com/ otherwise"""

        chart = PieChart2D(500,350,title="How Lazy are you?")
        chart.add_data(self.values)
        chart.set_pie_labels(self.keys)
        webbrowser.open_new_tab(chart.get_url())


class ReportOut(Report):
    def __init__(self,data):
        Report.__init__(self,data)

    def show(self):
        print "Usage Report:\n"
        for app in self.data.keys():
            print app + " = " + str(self.data[app])+"%"


class ReportFactory:
    @staticmethod
    def getReportType(data,options=None):
        if options.google:
            return PieGChart(data)
        elif options.stdoutreport:
            return ReportOut(data)
        else:
            return PieMatplotLib(data)


def main():
    parser = OptionParser()
    parser.add_option("-g","--google",action="store_true",dest="google",
                      help="uses the google chart api")
    parser.add_option("-s","--stdout",action="store_true",dest="stdoutreport",
                      help="ascii report in stdout")
    (options,args) = parser.parse_args()

    imlazy = Lazy()
    checkhowlazy = Command()
    try:
        id = None
        title = None
        while True:
            id = checkhowlazy.runGetId()
            if id:
                title = checkhowlazy.runGetTitle(id)
                if title:
                    imlazy.sumPercentage(title)
            time.sleep(2)
    except KeyboardInterrupt:
        lazylogger.info("Let's see how lazy you are ;)")
        report = ReportFactory.getReportType(imlazy.getPercentages(),options)
        report.calculate()
        report.show()
        sys.exit()

if __name__ == '__main__':
    main()

